package fr.bludwarf.skywarrior.xml;

import java.util.ArrayList;
import java.util.Date;

import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;

import fr.bludwarf.skywarrior.evenements.TerminerRecherche;
import fr.bludwarf.skywarrior.global.EtatMonde;
import fr.bludwarf.skywarrior.global.Monde;
import fr.bludwarf.skywarrior.global.Partie;
import fr.bludwarf.skywarrior.global.Temps;
import fr.bludwarf.skywarrior.ile.Ile;
import fr.bludwarf.skywarrior.joueur.EtatJoueur;
import fr.bludwarf.skywarrior.joueur.Joueur;
import fr.bludwarf.skywarrior.joueur.Ressources;
import fr.bludwarf.skywarrior.joueur.Techno;
import fr.bludwarf.skywarrior.joueur.Vaisseau;

@Root(name="etat")
public class EtatMondeXML extends SubElementXML<EtatMonde, Partie>
{
	
	/** date de la partie au moment de l'export */
	@Attribute
	Date date;
	
	@ElementList(inline=true)
	ArrayList<JoueurXML> joueurs;
	
	public EtatMondeXML()
	{
	}

	public EtatMondeXML(EtatMonde etat) throws Exception
	{
		this();
		fromObject(etat);
	}

	@Override
	public void fromObject(EtatMonde obj) throws Exception
	{
		date = obj.getDateReelle();
				
		joueurs = new ArrayList<EtatMondeXML.JoueurXML>();
		for (final Joueur joueur : obj.getJoueurs())
		{
			final EtatJoueur etatJoueur = obj.getEtatJoueur(joueur);
			final JoueurXML xml = new JoueurXML(etatJoueur);
			joueurs.add(xml);
		}
	}

	@Override
	public EtatMonde toObject(Partie partie) throws Exception
	{
		final EtatMonde obj = new EtatMonde(partie.getMonde(), new Temps(partie.getDebut(), date));
		
		for (final JoueurXML joueurXML : joueurs)
		{
			obj.add(joueurXML.toObject(obj));
		}
		
		return obj;
	}
	
	@Root(name="joueur")
	public static class JoueurXML extends SubElementXML<EtatJoueur, EtatMonde>
	{
		@Attribute
		String nom;
		
		@Attribute(required=false)
		int mat = EtatJoueur.STOCKS_INIT.materiaux();
		
		@Attribute(required=false)
		int eth = EtatJoueur.STOCKS_INIT.ether();
		
		@ElementList
		ArrayList<EtatIleXML> iles;
		
		@ElementList
		ArrayList<VaisseauXML> vaisseaux;
		
		@ElementList
		ArrayList<TechnoXML> technos;
		
		public JoueurXML()
		{
		}

		public JoueurXML(EtatJoueur etatJoueur) throws Exception
		{
			this();
			fromObject(etatJoueur);
		}

		@Override
		public EtatJoueur toObject(EtatMonde etatMonde) throws Exception
		{			
			final Monde monde = etatMonde.getMonde();
			final Joueur joueur = monde.getJoueur(nom);
			
			final EtatJoueur etatJoueur = new EtatJoueur(joueur, etatMonde);
			
			etatJoueur.setStocks(mat, eth);
			
			// Iles
			for (EtatIleXML ileXML : iles)
			{
				etatJoueur.add(ileXML.toObject(etatJoueur));
			}
			
			// Vaisseaux
			for (final VaisseauXML xml : vaisseaux)
			{
				xml.toObject(etatJoueur);
			}
			
			// Technos
			for (final TechnoXML xml : technos)
			{
				xml.toObject(etatJoueur);
			}
			
			return etatJoueur;
		}

		public void fromObject(EtatJoueur obj) throws Exception
		{
			final EtatJoueur etatJoueur = obj;
			final Joueur joueur = etatJoueur.getJoueur();
			nom = joueur.getNom();
			final Ressources stocks = obj.getStocks();
			mat = stocks.materiaux();
			eth = stocks.ether();
			
			// Iles
			iles = new ArrayList<EtatIleXML>();
			for (Ile ile : joueur.getIles())
			{
				final EtatIleXML etatIleXML = new EtatIleXML(etatJoueur.getEtatIle(ile));
				iles.add(etatIleXML);
			}
			
			// Vaisseaux
			vaisseaux = new ArrayList<EtatMondeXML.JoueurXML.VaisseauXML>();
			for (Vaisseau vaisseau : etatJoueur.getVaisseaux())
			{
				final int nb = etatJoueur.getNb(vaisseau);
				final VaisseauXML xml = new VaisseauXML(nb, vaisseau);
				vaisseaux.add(xml);
			}
			
			// Technos connues
			technos = new ArrayList<EtatMondeXML.JoueurXML.TechnoXML>();
			for (Techno techno : etatJoueur.getTechnos())
			{
				final TechnoXML xml = new TechnoXML(techno);
				technos.add(xml);
			}
			
			// Recherches
			for (TerminerRecherche rch : etatJoueur.getRecherches())
			{
				final TechnoXML xml = new TechnoXML(rch);
				technos.add(xml);
			}
		}
		
		@Root(name="vaisseau")
		public static class VaisseauXML
		{
			@Attribute
			String nom;
			
			@Attribute(required=false)
			int nb = 1;
			
			public VaisseauXML()
			{
			}

			public VaisseauXML(int nb, Vaisseau vaisseau)
			{
				this.nb = nb;
				nom = vaisseau.getNom();
			}

			public void toObject(EtatJoueur etatJoueur)
			{
				final Vaisseau vaisseau = Vaisseau.getVaisseau(nom);
				etatJoueur.add(nb, vaisseau);
			}
		}
		
		@Root(name="techno")
		public static class TechnoXML
		{
			@Attribute
			String nom;
			
			/** si absent alors techno connue, sinon techno en recherche */
			@Attribute(required=false, name="temps-restant")
			String tempsRestant;
			
			public TechnoXML()
			{
			}

			public TechnoXML(Techno techno)
			{
				nom = techno.getNom();
			}

			public TechnoXML(TerminerRecherche rch)
			{
				nom = rch.getTechno().getNom();
				tempsRestant = Temps.formatDuree(rch.getTempsRestant());
			}

			public void toObject(EtatJoueur etatJoueur)
					throws Exception
			{
				final Techno techno = Techno.getTechno(nom);
				
				// Techno connue
				if (tempsRestant == null)
				{
					etatJoueur.add(techno);
				}
				
				// Recherche
				else
				{
					final TerminerRecherche rch = new TerminerRecherche(etatJoueur.getJoueur(), techno, Temps.parseDuree(tempsRestant));
					etatJoueur.add(rch);
				}
			}

			public void fromObject(Techno obj, double tempsRestant)
					throws Exception
			{
				nom = obj.getNom();
				tempsRestant = obj.getTempsRecherche();
			}
		}
	}

}
